const micro = 1.0658141036401503e-14 // 定义一个极小量，运算结果绝对值小于它就算相等

module.exports = {
  /**
   * 两个数能否得到结果
   * @param {a} num 参数1
   * @param {b} num 参数2
   * @param {result} num 结果
   */
  C2(a, b, result) {
    let obj = new Object
    obj.op1 = a
    obj.op2 = b
    obj.result = result
    obj.findComputationMethods = function () {
      let arr = []
      if (Math.abs(this.result - (this.op1 + this.op2)) < micro) {
        arr.push({
          methods: this.op1 + "+" + this.op2,
          math: '+'
        }) // op1+op2
      }
      if (Math.abs(this.result - this.op1 * this.op2) < micro) {
        arr.push({
          methods: this.op1 + "×" + this.op2,
          math: '*'
        }) // op1*op2
      }
      if (Math.abs(this.result - (this.op1 - this.op2)) < micro) {
        arr.push({
          methods: this.op1 + "-" + this.op2,
          math: '-'
        }) // op1-op2
      }
      if (Math.abs(this.result - (this.op2 - this.op1)) < micro) {
        arr.push({
          methods: this.op2 + "-" + this.op1,
          math: '-'
        }) // op2-op1
      }
      if (Math.abs(this.result - this.op1 / this.op2) < micro) {
        arr.push({
          methods: this.op1 + "÷" + this.op2,
          math: '/'
        }) // op1/op2
      }
      if (Math.abs(this.result - this.op2 / this.op1) < micro) {
        arr.push({
          methods: this.op2 + "÷" + this.op1,
          math: '/'
        }) // op2/op1
      }
      return arr
    }
    return obj
  },
  /**
   * 三个数能否得到结果
   * @param {a} num 参数1
   * @param {b} num 参数2
   * @param {c} num 参数3
   * @param {result} num 结果
   */
  C3(a, b, c, result) {
    var obj = new Object
    obj.op1 = a
    obj.op2 = b
    obj.op3 = c
    obj.result = result
    let that = this
    obj.findComputationMethods = function () {
      var retArr = [] // 返回数组
      var permutationArr = [
        [this.op1, this.op2, this.op3],
        [this.op1, this.op3, this.op2],
        [this.op2, this.op1, this.op3],
        [this.op2, this.op3, this.op1],
        [this.op3, this.op2, this.op1],
        [this.op3, this.op1, this.op2],
      ] // 排列数组，三个操作数共有6种排列方式

      for (var i = 0; i < permutationArr.length; i++) {
        var arr = permutationArr[i]
        var op1 = arr[0]
        var op2 = arr[1]
        var op3 = arr[2]
        var c2 = that.C2(op1, op2, this.result + op3)
        var methods = c2.findComputationMethods()
        if (methods.length > 0) {
          for (var j = 0; j < methods.length; j++) {
            retArr.push({
              methods: methods[j].methods + "-" + op3,
              math: '-'
            }) // [op1,op2]-op3
          }
        }
        c2 = that.C2(op1, op2, this.result * op3)
        methods = c2.findComputationMethods()
        if (methods.length > 0) {
          for (var j = 0; j < methods.length; j++) {
            if (methods[j].math == '+' || methods[j].math == '-') {
              retArr.push({
                methods: '(' + methods[j].methods + ")" + "÷" + op3,
                math: '/'
              })
              // [op1,op2]/op3
            } else {
              retArr.push({
                methods: methods[j].methods + "÷" + op3,
                math: '/'
              }) // [op1,op2]/op3
            }
          }
        }
        c2 = that.C2(op1, op2, this.result - op3)
        methods = c2.findComputationMethods()
        if (methods.length > 0) {
          for (var j = 0; j < methods.length; j++) {
            retArr.push({
              methods: methods[j].methods + "+" + op3,
              math: '+'
            }) // [op1,op2]+op3
          }
        }
        c2 = that.C2(op1, op2, op3 - this.result)
        methods = c2.findComputationMethods()
        if (methods.length > 0) {
          for (var j = 0; j < methods.length; j++) {
            if (methods[j].math == '+' || methods[j].math == '-') {
              retArr.push({
                methods: op3 + "-" + '(' + methods[j].methods + ")",
                math: '-'
              }) // op3-[op1,+-,op2]
            } else {
              retArr.push({
                methods: op3 + "-" + methods[j].methods,
                math: '-'
              }) // op3-[op1,*/,op2]
            }
          }
        }
        c2 = that.C2(op1, op2, this.result / op3)
        methods = c2.findComputationMethods()
        if (methods.length > 0) {
          for (var j = 0; j < methods.length; j++) {
            if (methods[j].math == '+' || methods[j].math == '-') {
              retArr.push({
                methods: '(' + methods[j].methods + ")" + "×" + op3,
                math: '*'
              }) // [op1,op2]*op3
            } else {
              retArr.push({
                methods: methods[j].methods + "×" + op3,
                math: '*'
              }) // [op1,op2]*op3
            }
          }
        }
        c2 = that.C2(op1, op2, op3 / this.result)
        methods = c2.findComputationMethods()
        if (methods.length > 0) {
          for (var j = 0; j < methods.length; j++) {
            retArr.push({
              methods: op3 + "÷" + '(' + methods[j].methods + ")",
              math: '/'
            }) // op3/[op1,op2]
          }
        }
      }
      return retArr
    }
    return obj
  },
  /**
   * 四个数能否得到结果
   * @param {a} num 参数1
   * @param {b} num 参数2
   * @param {c} num 参数3
   * @param {d} num 参数4
   * @param {result} num 结果
   */
  C4(a, b, c, d, result) {
    var obj = new Object
    obj.op1 = a
    obj.op2 = b
    obj.op3 = c
    obj.op4 = d
    obj.result = result
    let that = this
    obj.findComputationMethods = function () {
      var retArr = [] // 返回数组
      var permutationArr = [
        [this.op1, this.op2, this.op3, this.op4],
        [this.op1, this.op2, this.op4, this.op3],
        [this.op1, this.op3, this.op2, this.op4],
        [this.op1, this.op3, this.op4, this.op2],
        [this.op1, this.op4, this.op2, this.op3],
        [this.op1, this.op4, this.op3, this.op2],
        [this.op2, this.op1, this.op3, this.op4],
        [this.op2, this.op1, this.op4, this.op3],
        [this.op2, this.op3, this.op1, this.op4],
        [this.op2, this.op3, this.op4, this.op1],
        [this.op2, this.op4, this.op1, this.op3],
        [this.op2, this.op4, this.op3, this.op1],
        [this.op3, this.op1, this.op2, this.op4],
        [this.op3, this.op1, this.op4, this.op2],
        [this.op3, this.op2, this.op1, this.op4],
        [this.op3, this.op2, this.op4, this.op1],
        [this.op3, this.op4, this.op1, this.op2],
        [this.op3, this.op4, this.op2, this.op1],
        [this.op4, this.op1, this.op2, this.op3],
        [this.op4, this.op1, this.op3, this.op2],
        [this.op4, this.op2, this.op1, this.op3],
        [this.op4, this.op2, this.op3, this.op1],
        [this.op4, this.op3, this.op1, this.op2],
        [this.op4, this.op3, this.op2, this.op1],
      ] // 排列数组，四个操作数共有24种排列方式
      for (var i = 0; i < permutationArr.length; i++) {
        var arr = permutationArr[i]
        var op1 = arr[0]
        var op2 = arr[1]
        var op3 = arr[2]
        var op4 = arr[3]
        var c3 = that.C3(op1, op2, op3, this.result + op4)
        var methods = c3.findComputationMethods()
        if (methods.length > 0) {
          for (var j = 0; j < methods.length; j++) {
            retArr.push(methods[j].methods + "-" + op4) // [op1,op2,op3]-op4
          }
        }
        var c3 = that.C3(op1, op2, op3, this.result * op4)
        var methods = c3.findComputationMethods()
        if (methods.length > 0) {
          for (var j = 0; j < methods.length; j++) {
            retArr.push(methods[j].methods + "÷" + op4) // [op1,op2,op3]/op4
          }
        }
        var c3 = that.C3(op1, op2, op3, this.result - op4)
        var methods = c3.findComputationMethods()
        if (methods.length > 0) {
          for (var j = 0; j < methods.length; j++) {
            retArr.push(methods[j].methods + "+" + op4) // [op1,op2,op3]+op4
          }
        }
        var c3 = that.C3(op1, op2, op3, op4 - this.result)
        var methods = c3.findComputationMethods()
        if (methods.length > 0) {
          for (var j = 0; j < methods.length; j++) {
            if (methods[j].math == '+' || methods[j].math == '-') {
              retArr.push(op4 + "-" + '(' + methods[j].methods + ")") // op4-[op1,op2,op3]
            } else {
              retArr.push(op4 + "-" + methods[j].methods) // op4-[op1,op2,op3]
            }
          }
        }
        var c3 = that.C3(op1, op2, op3, this.result / op4)
        var methods = c3.findComputationMethods()
        if (methods.length > 0) {
          for (var j = 0; j < methods.length; j++) {
            if (methods[j].math == '+' || methods[j].math == '-') {
              retArr.push('(' + methods[j].methods + ")" + "×" + op4) // [op1,op2,op3]*op4
            } else {
              retArr.push(methods[j].methods + "×" + op4) // [op1,op2,op3]*op4
            }
          }
        }
        var c3 = that.C3(op1, op2, op3, op4 / this.result)
        var methods = c3.findComputationMethods()
        if (methods.length > 0) {
          for (var j = 0; j < methods.length; j++) {
            retArr.push(op4 + "÷" + '(' + methods[j].methods + ")") // op4/[op1,op2,op3]
          }
        }
        if (Math.abs(this.result - (op1 - op2) * (op3 - op4)) < micro) {
          retArr.push("("+op1 + "-" + op2 + ")×(" + op3 + "-" + op4+")") // (op1-op2)*(op3-op4),这是c3里不曾有的
        }
        if (Math.abs(this.result - (op1 - op2) * (op3 + op4)) < micro) {
          retArr.push("("+op1 + "-" + op2 + ")×(" + op3 + "+" + op4+")") // (op1-op2)*(op3+op4),这是c3里不曾有的
        }
        if (Math.abs(this.result - (op1 + op2) * (op3 + op4)) < micro) {
          retArr.push("("+op1 + "-" + op2 + ")×(" + op3 + "-" + op4+")") // (op1+op2)*(op3+op4),这是c3里不曾有的
        }
        if (Math.abs(this.result - (op1 + op2) / (op3 + op4)) < micro) {
          retArr.push("("+op1 + "+" + op2 + ")÷(" + op3 + "+" + op4+")") // (op1+op2)/(op3+op4),这是c3里不曾有的
        }
        if (Math.abs(this.result - (op1 + op2) / (op3 - op4)) < micro) {
          retArr.push("("+op1 + "+" + op2 + ")÷(" + op3 + "-" + op4+")") // (op1+op2)/(op3-op4),这是c3里不曾有的
        }
        if (Math.abs(this.result - (op1 * op2 - op3 * op4)) < micro) {
          retArr.push(op1 + "×" + op2 + "-" + op3 + "×" + op4) // op1*op2-op3*op4,这是c3里不曾有的
        }
        if (Math.abs(this.result - (op1 * op2 + op3 * op4)) < micro) {
          retArr.push(op1 + "×" + op2 + "+" + op3 + "×" + op4) // op1*op2+op3*op4,这是c3里不曾有的
        }
        if (Math.abs(this.result - (op1 / op2 - op3 / op4)) < micro) {
          retArr.push(op1 + "÷" + op2 + "-" + op3 + "÷" + op4) // op1/op2-op3/op4,这是c3里不曾有的
        }
        if (Math.abs(this.result - (op1 / op2 + op3 / op4)) < micro) {
          retArr.push(op1 + "÷" + op2 + "+" + op3 + "÷" + op4) // op1/op2+op3/op4,这是c3里不曾有的
        }
        if (Math.abs(this.result - (op1 * op2 - op3 / op4)) < micro) {
          retArr.push(op1 + "*" + op2 + "-" + op3 + "÷" + op4) // op1*op2-op3/op4,这是c3里不曾有的
        }
        if (Math.abs(this.result - (op1 * op2 + op3 / op4)) < micro) {
          retArr.push(op1 + "*" + op2 + "+" + op3 + "÷" + op4) // op1*op2+op3/op4,这是c3里不曾有的
        }
      }
      return retArr
    }
    return obj
  },
  /*
   * 用来得到仅包含不重复元素的数组
   */
  getDistinctArray(arr) {
    var returnArr = new Array()
    var sortedArr = arr.sort()
    for (var i = 0; i < sortedArr.length; i++) {
      if (returnArr[returnArr.length - 1] != sortedArr[i]) {
        returnArr.push(sortedArr[i])
      }
    }
    return returnArr
  },
  /**
   * 四个数能否得到结果
   * @param {array} 
   */
  main(array) {
    let op1 = array[0]
    let op2 = array[1]
    let op3 = array[2]
    let op4 = array[3]
    let c4 = this.C4(op1, op2, op3, op4, 24) //result
    let arr = this.getDistinctArray(c4.findComputationMethods())
    if (arr.length > 0) {
      let ratio = this.ratioMath(arr)
      for (let i = 0; i < arr.length; i++) {
        // console.log(arr[i] + "=24")
      }
      return {
        arr,
        ratio
      }
    } else {
      return false
    }
  },
  /**
   * 四个数能否得到结果
   * @param {a} num 参数1
   * @param {b} num 参数2
   * @param {c} num 参数3
   * @param {d} num 参数4
   * @param {result} num 结果
   */
  mainC(a, b, c, d) {
    let op1 = a
    let op2 = b
    let op3 = c
    let op4 = d
    let c4 = this.C4(op1, op2, op3, op4, 24) //result
    let arr = this.getDistinctArray(c4.findComputationMethods())
    if (arr.length > 0) {
      let ratio = this.ratioMath(arr)
      for (let i = 0; i < arr.length; i++) {
        // console.log(arr[i] + "=24")
      }
      return {
        arr,
        ratio
      }
    } else {
      return false
    }
  },
  /* 难度分析 */
  ratioMath(array) {
    let base_num = 10
    let ratio_idx = 1.5
    let is_length = array.length
    let count = 0
    array.forEach(i => {
      if (i.indexOf('(') != -1) {
        let brakets_idx = i.indexOf('(')
        count++
        let rev_brakets_idx = i.lastIndexOf('(')
        if (brakets_idx != rev_brakets_idx) {
          count++
        }
      }
    })
    /* ÷ */
    array.forEach(i => {
      if (i.indexOf('×') != -1 && i.indexOf('÷') != -1) {
        ratio_idx = 3
      } else if (i.indexOf('×') != -1 || i.indexOf('÷') != -1) {
        ratio_idx = 2
      }
    })
    let brakets_ratio = Math.floor(count / is_length * 10 + 10)
    let ratio = Math.floor(base_num * ratio_idx + brakets_ratio)
    return ratio
  }
}